Loading
首页
文章分类
技术教程
知识积累
新闻日报
知识分享
今日新闻
其他页面
网站统计
友情链接
高清壁纸
虎牙直播
关于轩灵
热门文章
VS2019避免全部安装至C盘
2023-04月17号更新v2
中兴F450光猫破解隐藏模式让路由器拨号
影子系统出现BAD_SYSTEM_CONFIG_INFO蓝屏问题
WPS专业版密钥经常提示过期解决方案
标签搜索
windows
linux
python
centos
centos7
网络技术
android
win11
windows 11
游戏
系统重装
Deepseek
ai
安卓
系统
Ubuntu
docker
windows server
vmware
esxi
发布
登录
注册
找到
122
篇与
技术
相关的结果
- 第 14 页
2018-10-08
SpringBoot多数据源unsatisfied dependency expressed through method 'entityManagerFactoryBuilder...
本来的项目(基于SpringBoot 2.0.5-RELEASE)集成了JPA、mybatis的注解、XML方式访问DB。 后面集成多数据源的时候启动SpringBoot时出现了如下错误: ERROR 32320 — [main] com.zaxxer.hikari.HikariConfig : HikariPool-1 - jdbcUrl is required with driverClassName. Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘entityManagerFactory’ defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unsatisfied dependency expressed through method ‘entityManagerFactory’ parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘entityManagerFactoryBuilder’ defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unsatisfied dependency expressed through method ‘entityManagerFactoryBuilder’ parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘jpaVendorAdapter’ defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.orm.jpa.JpaVendorAdapter]: Factory method ‘jpaVendorAdapter’ threw exception; nested exception is java.lang.IllegalArgumentException: jdbcUrl is required with driverClassName. at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:732) at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:474) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1247) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1096) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:535) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:495) at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1089) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:859) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:780) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:412) at org.springframework.boot.SpringApplication.run(SpringApplication.java:333) at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:139) at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99) at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:117) … 24 more 后来查看了源码,流程如下: @Bean(name = "test1DataSource") @ConfigurationProperties(prefix = "spring.datasource") @Primary public DataSource testDataSource() { return DataSourceBuilder.create().build(); }进入DataSourceBuilder.create().build(): public T build() { Class<? extends DataSource> type = getType(); DataSource result = BeanUtils.instantiateClass(type); maybeGetDriverClassName(); bind(result); return (T) result; }maybeGetDriverClassName(); 方法: private void maybeGetDriverClassName() { if (!this.properties.containsKey("driverClassName") && this.properties.containsKey("url")) { String url = this.properties.get("url"); String driverClass = DatabaseDriver.fromJdbcUrl(url).getDriverClassName(); this.properties.put("driverClassName", driverClass); } }bind(result) 方法: private void bind(DataSource result) { ConfigurationPropertySource source = new MapConfigurationPropertySource( this.properties); ConfigurationPropertyNameAliases aliases = new ConfigurationPropertyNameAliases(); aliases.addAliases("url", "jdbc-url"); aliases.addAliases("username", "user"); Binder binder = new Binder(source.withAliases(aliases)); binder.bind(ConfigurationPropertyName.EMPTY, Bindable.ofInstance(result)); }因为springboot首推的连接池使用了HikariCP连接池,GET到这个点, HikariDataSource的获取数据库连接的getConnection方法: @Override public Connection getConnection() throws SQLException { if (isClosed()) { throw new SQLException("HikariDataSource " + this + " has been closed."); } if (fastPathPool != null) { return fastPathPool.getConnection(); } // See http://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java HikariPool result = pool; if (result == null) { synchronized (this) { result = pool; if (result == null) { validate(); LOGGER.info("{} - Starting...", getPoolName()); try { pool = result = new HikariPool(this); this.seal(); } catch (PoolInitializationException pie) { if (pie.getCause() instanceof SQLException) { throw (SQLException) pie.getCause(); } else { throw pie; } } LOGGER.info("{} - Start completed.", getPoolName()); } } } return result.getConnection(); }HikariConfig的validate方法 public void validate() { if (poolName == null) { poolName = generatePoolName(); } else if (isRegisterMbeans && poolName.contains(":")) { throw new IllegalArgumentException("poolName cannot contain ':' when used with JMX"); } // treat empty property as null catalog = getNullIfEmpty(catalog); connectionInitSql = getNullIfEmpty(connectionInitSql); connectionTestQuery = getNullIfEmpty(connectionTestQuery); transactionIsolationName = getNullIfEmpty(transactionIsolationName); dataSourceClassName = getNullIfEmpty(dataSourceClassName); dataSourceJndiName = getNullIfEmpty(dataSourceJndiName); driverClassName = getNullIfEmpty(driverClassName); jdbcUrl = getNullIfEmpty(jdbcUrl); // Check Data Source Options if (dataSource != null) { if (dataSourceClassName != null) { LOGGER.warn("{} - using dataSource and ignoring dataSourceClassName.", poolName); } } else if (dataSourceClassName != null) { if (driverClassName != null) { LOGGER.error("{} - cannot use driverClassName and dataSourceClassName together.", poolName); // NOTE: This exception text is referenced by a Spring Boot FailureAnalyzer, it should not be // changed without first notifying the Spring Boot developers. throw new IllegalStateException("cannot use driverClassName and dataSourceClassName together."); } else if (jdbcUrl != null) { LOGGER.warn("{} - using dataSourceClassName and ignoring jdbcUrl.", poolName); } } else if (jdbcUrl != null || dataSourceJndiName != null) { // ok } else if (driverClassName != null) { LOGGER.error("{} - jdbcUrl is required with driverClassName.", poolName); throw new IllegalArgumentException("jdbcUrl is required with driverClassName."); } else { LOGGER.error("{} - dataSource or dataSourceClassName or jdbcUrl is required.", poolName); throw new IllegalArgumentException("dataSource or dataSourceClassName or jdbcUrl is required."); } validateNumerics(); if (LOGGER.isDebugEnabled() || unitTest) { logConfiguration(); } }这个if分支: jdbcUrl = getNullIfEmpty(jdbcUrl); else if (driverClassName != null) { LOGGER.error("{} - jdbcUrl is required with driverClassName.", poolName); throw new IllegalArgumentException("jdbcUrl is required with driverClassName."); }这里要求DataSource的参数存在 jdbcUrl 、以及driverClassName,而我们的配置是: spring.datasource.url=jdbc:mysql://localhost:3306/mypydb spring.datasource.username=root spring.datasource.password=11111111 spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource2.url=jdbc:mysql://localhost:3306/mypydb2 spring.datasource2.username=root spring.datasource2.password=11111111 spring.datasource2.driver-class-name=com.mysql.jdbc.Driver所以将url改为 jdbc-url 即可。 spring.datasource.jdbc-url=jdbc:mysql://localhost:3306/mypydb spring.datasource2.jdbc-url=jdbc:mysql://localhost:3306/mypydb2
技术
分享
轩灵
2018-10-08
0
2,012
118
2018-10-03
Git核心命令会这些就够了
git 与 svn 的区别 存储方式 使用方式 管理模式 git 提交代码流程 本地开发分支,使用 add 命令将修改的内容添加到本地缓存空间,通过 commit 命令将添加的内容提交到本地仓库, push 命令将本地仓库的内容提交到关联的远程仓库。 DEVER -------(add) --> local cache ------(commit)--> local repository -------(push)--> remote repositorySVN 管理模式 local --> remote remote挂了,导致本地不能做任何操作GIT 管理模式 git 本地可以做remote一样的操作。 git可以关联多个远程仓库。 git remote还可以备份。 git使用K-V存储数据。SVN使用复制版本完成可回滚操作。git 核心命令 创建、克隆、添加、提交、push、pull、更新、关联远程 - 创建git项目,生成一个 .git 目录 git init git remote add origin XXX.git echo 'You is a bad man, haha!' > readme.md git status git add -A git commit -m '提交记录' git push --set-upstream origin master (首次),后面git push即可 git pull git clone XXX.git 本地目录名管理模式 mkdir -p src/main/java/com echo 'package com' > hello.java git remove --cached target -r git commit -am '注释' git commit -m '注释'分支 git branch : #显示本地分支 git branch -av : #包含显示远程分支 git branch -avv : #包含显示远程分支,包含关联信息 git branch 新分支name :# 基于当前分支新建分支 git branch 新分支name #已存在分支 :# 基于已存在分支新建分支 git branch 新分支name commitid :# 基于提交id新建分支 git checkout 分支名 : #切换分支 git branch -d 分支名: # 删除分支 git merge branch : #将branch合并到当前分支远程仓库 git remote -v : #查看远程信息 git remote add origin XXX.git git remote add origin2 XXX.git git push --upstream origin2 master : #推送到关联的第二个仓库 git push origin[2] git remote remove 远程仓库名 : # 删除关联的远程仓库日志 git log: # 查看提交日志 git log --online : # 一行行的查看 git log branch --online: # 查看分支的日志 git log dev..master : # master有多少提交没有同步到dev来。 git log --graph --online : #查看提交网络图 git show [commitId]: #展示变更的内容恢复历史 reset 场景: 当我们提交了错误的代码后,想回归到原来的某个版本 可以使用 reset 操作。 git help reset语法 将当前分支的head指向指定的commitid状态, work tree 依赖于模式mode。 git reset [#mode#] [#commit#]把#号替换成尖括号mode 的值: –soft :不会改变index文件和working tree,仅仅将head指向了commitid,使用git sattus查看时,发现是尚未提交的,你需要手动进行commit。 –mixed :这是默认值。重设index文件,但是不会改变working tree。更改后的文件被保留,但是不会被标记为commited。 –hard :重设index文件和working tree。所有在commitid后发生的改变均会舍弃掉。 –merge:合并,意义不大。commitid和当前head版本中的某个文件在本地被改变的话就会放弃reset。 –keep:commitid和当前head版本中的某个文件在本地被改变的话就会放弃reset。 例如:回退到commitid 1a02031a7d86684246d878a58ff4e1601f14afb7 的版本。 git reset 1a02031a7d86684246d878a58ff4e1601f14afb7此时,远程分支的代码已经在commitid版本之后了,所以push会失败,可以使用强制push覆盖掉远程代码库。 git push -f origingit 原理 git 存储对象 git 是一个内容寻址文件系统,核心是一个简单的KV数据库,插入任意内容会返回一个用于取回该值的hash。 find .git/objects/ -type f : 查找所有的git对象 git hash-object -w README.md git cat-file -p commitId > README.md : # 回滚内容,可以将commitId的内容写入到README.md中,完成了一次回滚的操作 git cat-file -t commitID : # 查看数据类型 > git add 会在objects添加对象。 > 使用后可以 用 find .git/objects -type f 查看是否新增了对象。 bash $ find .git/objects -type f .git/objects/69/f22ff2d6d6d4d8288fa9fa99ac2d58927ab1d6 .git/objects/99/f5369cae277ef56123d0012e2ef952e2e9d825 $ git add git基础.md $ find .git/objects -type f .git/objects/69/f22ff2d6d6d4d8288fa9fa99ac2d58927ab1d6 .git/objects/90/0aabe1fb581794dd7e5cd238828f112f5109af #新增的 .git/objects/99/f5369cae277ef56123d0012e2ef952e2e9d825搭建企业私有git服务 git 支持的协议 local 协议 本地共享目录; 快速;简单;局域网; 速度慢; 仅仅小项目; D盘创建仓库: git init --bare hello.git : 创建一个裸项目E盘克隆: git clone /d/XXX/git这样本地仓库在E盘,远程分支在D盘,就是一个基本的git服务了。 ssh 协议 git init --bare hello.git : 创建一个裸项目 git clone root@ip:XXX.git ssh-keygenhttp 协议 nginx 是基础(3 years experience) git协议 一般不用 基于 gogs 开发企业git web 服务 比 gitlab 轻便 下载gogs版本 https://github.com/gogs/gogs/releases 选择要下载的版本 解压运行 在解压后的根目录下执行 gogs.exe web访问gogs web 服务 http://localhost:3000/ 可以看到gogs服务启动成功 首次配置 第一次进入web页面进行配置信息 gogs 备份 gogs.exe backup会在根目录生成一个备份文件如: gogs-backup-20181004183106.zip gogs 恢复 gogs.exe restore --from=gogs-backup-20181004183106.zip
技术
分享
轩灵
2018-10-03
0
1,717
177
2018-09-21
开机到桌面弹出一分钟重启解决办法
1.强制关机(按住电源键10S以上)后再开机,重复三次以上,或者按住shift选择重启,系统会自动进入蓝屏选择项界面,选择“查看高级修复选项或者疑难解答” 2. 高级修复如果没有启动设置,点查看更多恢复选项,选择启动设置,点击重启 3. 自动开机会进开机模式选择,按4或者F4进入安全模式 4.开机到桌面,此时按WIN+X,选择命令提示符(管理员)或者Windows PowerShell(管理员) 5.输入 netsh winsock reset按回车执行,出现错误提示不要管 只看最后一条重置成功就行,然后重启电脑
技术
分享
# windows
轩灵
2018-09-21
0
2,206
132
2018-09-20
【机械师】重装系统讲解
1. 为什么新机子要重装系统 【群文件 四、售后 优化 重装系统】——1. 收货及需要做什么 的里面,最下面的5. 新机子为什么要重装系统,已经说的话很明白了,自己去看看。 1. 机械师出厂除个别型号外,其余没有系统。没人会一步步按照教程给你安装,因为太废时间,所以使用时拷贝系统,也就是常见ghost系统,关于ghost系统,仁者见仁智者见智,ghost有优点也有缺点,如果想要了解更多,请百度 2. 一般你们收到的系统都是仓库调试给你们预装的,(F3k B6 pX780正版), 后面我会解释,我不能说你们收到的都是有问题的,但肯定会有一部分有问题。 咱们先说说重装系统的好处: 2. 重装系统的好处 1.杀死木马病毒 重装系统可以杀毒,大部分用户使用的是FORMAT格式化命令,FORMAT会清空操作系统盘符数据,当然木马病毒也一同杀死了。 2.提高系统稳定性提高 纯净的操作系统稳定性最好,随着用户各种应用、驱动程序加载,特别是设计有缺陷、错误连连的应用软件,会对系统的安全稳定性带来隐患,尤其是系统各种错误提示增多,重装系统可以解决这个问题。 3.提高系统运行速度 系统用的时间长了,内置的软件、冗余注册表值、临时数据都会拖累操作系统运行速度,重装系统是直接有效的提速方式。 4.清理系统垃圾 清理系统垃圾体现在常年累月的使用系统,造成数据堆积过多。重装系统将数据清空,重新复制系统文件,身材自然会小一圈。 5.重装系统有利于数据碎片整理 重装系统有利于提高硬盘空间的利用率,通过格式化硬盘数据,抹去了长期运行遗留到硬盘的数据碎片,从而提高硬盘寿命。(针对于机械硬盘) 机械硬盘平常使用就可以碎片清理了 6.修复缺失的系统文件 有相当部分的程序失灵,是由原系统文件丢失、受损造成的。利用重装系统,可以修复文件受损造成的系统困惑。 7.系统崩溃时的唯一选择 系统崩溃时,除了重装系统,还有什么办法?唯一能做主的是花钱重装,还是自己动手重装,总之就是重装。 8.还原用户操作习惯 假如我习惯了浏览器操作方式(计算机),有一款工具条把浏览器操作恶意修改了,就会给我的使用带来麻烦,重装系统就可以解决。 9.还原用户喜爱版本 并不是所有win10的版本都适合你,重装给你不同的版本享受。 10. 一些作死行为最快解决方法 比如(凹凸曼)有时候学技术,改东西改了乱七八糟,不知道怎么弄回来,就是重装系统 3. 原版、正版、定制版、盗版 win10系统的简述 1. 原版系统 微软官方下载的win10原版镜像系统,未经过任何修改,统一称为原版系统。 MSDN 所提供的也是win10原版系统。 2. 正版系统 购买微软正版win10系统,无论是系统联网自己激活的,或是用秘钥批量激活的,还是正版系统光盘里秘钥激活的,只要有微软官方授权的,统称为正版win10系统。 很贵,最便宜写入主办的也需要300,win10家庭版900,专业版本1400左右。 3. 定制版系统 在中国,各种所谓的定制版本,都是基于原版系统离线修改优化而成,他们都根据自己的需求,对原版系统做了更改。 4. 盗版系统 不论你是不是原版,还是定制版,还是各种论坛提供的,还是外面电脑店给你装的,只要不用正版激活秘钥激活的,没有微软官方授权的,没有花大价钱的买的系统, 软件激活 秘钥激活 各种激活的 都是 盗版系统。(名义上) 4. 盗版kms激活、正版激活、淘宝15元买的秘钥 区别 机械师目前自带正版系统只有F117-F3K、F117-F6G,B6如果后续机型有自带正版,请以客服为准。 一、 KMS激活: KMS(Windows密钥管理服务)_百度百科https://baike.baidu.com/item/KMS/66195?fr=aladdin 二、 正版激活:正版购买数字秘钥 花了很多钱,支持了正版,表扬你的正版意识。但,买笔记本电脑的很多都是学生,支持不起,太贵了,900的家庭,1400的专业,我选择数字权利。 三、 数字权利激活: win10系统的上线同时一个全新的激活机制上线,激活将绑定你的微软账户!绑定账户后显示Windows已与Microsoft关联的数字许可证激活,数字许可证就是你的数字秘钥,这个激活可以通过洗白,秘钥,msdn订阅等获得!数字激活永久激活,这台电脑只要是还能用你登录你获得数字许可证的账户就会自动激活,可以跟随最新的更新,系统稳定性强。 淘宝15元,和正版一模一样,没任何区别。 四、 大白话: 1. 我感觉其实KMS和数字权利激活,在日常使用没有近乎没有区别。但是,KMS会被win10安全中心报错,而且,你怎么知道你使用的KMS是安全没有放病毒的?另外由组织的服务器激活的180天后,你需要重新激活一次。 2. 第二,我在群文件提供的KMS激活那是绝对安全的,没有病毒的,你们只需要180天点击一次就OK。但是,如果涉及到出国,在国外你使用W10系统是必须使用数字权利激活的。数字激活,绑定自己的微软邮箱,相当于一劳永逸。 3. 另外,kms激活前电脑是w10专业版系统,用了KMS激活就变成了教育版、家庭版,虽然这些版本的使用对于你们并没有区别,但是谁放这专业版不要,要用“便宜的”家庭、教育版本? 4. 淘宝直接搜索win10,会有店铺提供win10激活秘钥,win10专业版。不支持重装的便宜,支持重装的稍微贵一些,其实秘钥这玩意,看你怎么想。 打个广告,群里也卖win10秘钥,和淘宝相比贵一二块钱,流量少进价高。 机械师俱乐部门诊部 群号:482960296,进群后看群公告和群文件,找管理即可。 详情参见 群文件 一 规章制度 群规,不希望enmm,被误解,所以群规写的很清楚。 本文转自机械师俱乐部贴吧群
默认分类
技术
分享
# windows
轩灵
2018-09-20
0
1,402
105
2018-08-14
【JVM】JAVA垃圾回收算法与垃圾回收器
Java中的垃圾回收一般是在Java堆中进行,因为堆中几乎存放了Java中所有的对象实例。谈到Java堆中的垃圾回收,自然要谈到引用。在JDK1.2之前,Java中的引用定义很很纯粹:如果reference类型的数据中存储的数值代表的是另外一块内存的起始地址,就称这块内存代表着一个引用。但在JDK1.2之后,Java对引用的概念进行了扩充,将其分为强引用(Strong Reference)、软引用(Soft Reference)、弱引用(Weak Reference)、虚引用(Phantom Reference)四种,引用强度依次减弱。 强引用:如“Object obj = new Object()”,这类引用是Java程序中最普遍的。只要强引用还存在,垃圾收集器就永远不会回收掉被引用的对象。 软引用:它用来描述一些可能还有用,但并非必须的对象。在系统内存不够用时,这类引用关联的对象将被垃圾收集器回收。JDK1.2之后提供了SoftReference类来实现软引用。 弱引用:它也是用来描述非需对象的,但它的强度比软引用更弱些,被弱引用关联的对象只能生存岛下一次垃圾收集发生之前。当垃圾收集器工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。在JDK1.2之后,提供了WeakReference类来实现弱引用。 虚引用:最弱的一种引用关系,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的是希望能在这个对象被收集器回收时收到一个系统通知。JDK1.2之后提供了PhantomReference类来实现虚引用。垃圾对象的判定 Java堆中存放着几乎所有的对象实例,垃圾收集器对堆中的对象进行回收前,要先确定这些对象是否还有用,判定对象是否为垃圾对象有如下算法: 引用计数算法 给对象添加一个引用计数器,每当有一个地方引用它时,计数器值就加1,当引用失效时,计数器值就减1,任何时刻计数器都为0的对象就是不可能再被使用的。 引用计数算法的实现简单,判定效率也很高,在大部分情况下它都是一个不错的选择,当Java语言并没有选择这种算法来进行垃圾回收,主要原因是它很难解决对象之间的相互循环引用问题。 根搜索算法 Java和C#中都是采用根搜索算法来判定对象是否存活的。这种算法的基本思路是通过一系列名为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,就证明此对象是不可用的。在Java语言里,可作为GC Roots的兑现包括下面几种: 虚拟机栈(栈帧中的本地变量表)中引用的对象。 方法区中的类静态属性引用的对象。 方法区中的常量引用的对象。 本地方法栈中JNI(Native方法)的引用对象。 实际上,在根搜索算法中,要真正宣告一个对象死亡,至少要经历两次标记过程:如果对象在进行根搜索后发现没有与GC Roots相连接的引用链,那它会被第一次标记并且进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法。当对象没有覆盖finalize()方法,或finalize()方法已经被虚拟机调用过,虚拟机将这两种情况都视为没有必要执行。如果该对象被判定为有必要执行finalize()方法,那么这个对象将会被放置在一个名为F-Queue队列中,并在稍后由一条由虚拟机自动建立的、低优先级的Finalizer线程去执行finalize()方法。finalize()方法是对象逃脱死亡命运的最后一次机会(因为一个对象的finalize()方法最多只会被系统自动调用一次),稍后GC将对F-Queue中的对象进行第二次小规模的标记,如果要在finalize()方法中成功拯救自己,只要在finalize()方法中让该对象重引用链上的任何一个对象建立关联即可。而如果对象这时还没有关联到任何链上的引用,那它就会被回收掉。 垃圾收集算法 判定除了垃圾对象之后,便可以进行垃圾回收了。下面介绍一些垃圾收集算法,由于垃圾收集算法的实现涉及大量的程序细节,因此这里主要是阐明各算法的实现思想,而不去细论算法的具体实现。 标记—清除算法 标记—清除算法是最基础的收集算法,它分为“标记”和“清除”两个阶段:首先标记出所需回收的对象,在标记完成后统一回收掉所有被标记的对象,它的标记过程其实就是前面的根搜索算法中判定垃圾对象的标记过程。 该算法有如下缺点: 标记和清除过程的效率都不高。 标记清除后会产生大量不连续的内存碎片,空间碎片太多可能会导致,当程序在以后的运行过程中需要分配较大对象时无法找到足够的连续内存而不得不触发另一次垃圾收集动作。 复制算法 复制算法是针对标记—清除算法的缺点,在其基础上进行改进而得到的,它讲课用内存按容量分为大小相等的两块,每次只使用其中的一块,当这一块的内存用完了,就将还存活着的对象复制到另外一块内存上面,然后再把已使用过的内存空间一次清理掉。复制算法有如下优点: 每次只对一块内存进行回收,运行高效。 只需移动栈顶指针,按顺序分配内存即可,实现简单。 内存回收时不用考虑内存碎片的出现。 它的缺点是:可一次性分配的最大内存缩小了一半。 标记—整理算法 复制算法比较适合于新生代,在老年代中,对象存活率比较高,如果执行较多的复制操作,效率将会变低,所以老年代一般会选用其他算法,如标记—整理算法。该算法标记的过程与标记—清除算法中的标记过程一样,但对标记后出的垃圾对象的处理情况有所不同,它不是直接对可回收对象进行清理,而是让所有的对象都向一端移动,然后直接清理掉端边界以外的内存。 分代收集 当前商业虚拟机的垃圾收集 都采用分代收集,它根据对象的存活周期的不同将内存划分为几块,一般是把Java堆分为新生代和老年代。在新生代中,每次垃圾收集时都会发现有大量对象死去,只有少量存活,因此可选用复制算法来完成收集,而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用标记—清除算法或标记—整理算法来进行回收。 垃圾收集器 垃圾收集器是内存回收算法的具体实现,Java虚拟机规范中对垃圾收集器应该如何实现并没有任何规定,因此不同厂商、不同版本的虚拟机所提供的垃圾收集器都可能会有很大的差别。Sun HotSpot虚拟机1.6版包含了如下收集器:Serial、ParNew、Parallel Scavenge、CMS、Serial Old、Parallel Old。这些收集器以不同的组合形式配合工作来完成不同分代区的垃圾收集工作。 垃圾回收分析 在用代码分析之前,我们对内存的分配策略明确以下三点: 对象优先在Eden分配。 大对象直接进入老年代。 长期存活的对象将进入老年代。 对垃圾回收策略说明以下两点: 新生代GC(Minor GC):发生在新生代的垃圾收集动作,因为Java对象大多都具有朝生夕灭的特性,因此Minor GC非常频繁,一般回收速度也比较快。 老年代GC(Major GC/Full GC):发生在老年代的GC,出现了Major GC,经常会伴随至少一次Minor GC。由于老年代中的对象生命周期比较长,因此Major GC并不频繁,一般都是等待老年代满了后才进行Full GC,而且其速度一般会比Minor GC慢10倍以上。另外,如果分配了Direct Memory,在老年代中进行Full GC时,会顺便清理掉Direct Memory中的废弃对象。 下面我们来看如下代码: ```git public class SlotGc{ public static void main(String[] args){ byte[] holder = new byte[32*1024*1024]; System.gc(); } } ``` 代码很简单,就是向内存中填充了32MB的数据,然后通过虚拟机进行垃圾收集。在Javac编译后,我们执行如下指令:java -verbose:gc SlotGc来查看垃圾收集的结果,得到如下输出信息: ```git [GC 208K->134K(5056K), 0.0017306 secs] [Full GC 134K->134K(5056K), 0.0121194 secs] [Full GC 32902K->32902K(37828K), 0.0094149 sec ``` 注意第三行,“->”之前的数据表示垃圾回收前堆中存活对象所占用的内存大小,“->”之后的数据表示垃圾回收堆中存活对象所占用的内存大小,括号中的数据表示堆内存的总容量,0.0094149 sec 表示垃圾回收所用的时间。 从结果中可以看出,System.gc(()运行后并没有回收掉这32MB的内存,这应该是意料之中的结果,因为变量holder还处在作用域内,虚拟机自然不会回收掉holder引用的对象所占用的内存。 我们把代码修改如下: ```git public class SlotGc{ public static void main(String[] args){ { byte[] holder = new byte[32*1024*1024]; } System.gc(); } } ``` 加入花括号后,holder的作用域被限制在了花括号之内,因此,在执行System.gc()时,holder引用已经不能再被访问,逻辑上来讲,这次应该会回收掉holder引用的对象所占的内存。但查看垃圾回收情况时,输出信息如下: ```git [GC 208K->134K(5056K), 0.0017100 secs] [Full GC 134K->134K(5056K), 0.0125887 secs] [Full GC 32902K->32902K(37828K), 0.0089226 secs] ``` 很明显,这32MB的数据并没有被回收。下面我们再做如下修改: ```git public class SlotGc{ public static void main(String[] args){ { byte[] holder = new byte[32*1024*1024]; holder = null; } System.gc(); } } ``` 这次得到的垃圾回收信息如下: ```git [GC 208K->134K(5056K), 0.0017194 secs] [Full GC 134K->134K(5056K), 0.0124656 secs] [Full GC 32902K->134K(37828K), 0.0091637 secs] ``` 说明这次holder引用的对象所占的内存被回收了。我们慢慢来分析。 首先明确一点:holder能否被回收的根本原因是局部变量表中的Slot是否还存有关于holder数组对象的引用。 在第一次修改中,虽然在holder作用域之外进行回收,但是在此之后,没有对局部变量表的读写操作,holder所占用的Slot还没有被其他变量所复用(回忆Java内存区域与内存溢出一文中关于Slot的讲解),所以作为GC Roots一部分的局部变量表仍保持者对它的关联。这种关联没有被及时打断,因此GC收集器不会将holder引用的对象内存回收掉。 在第二次修改中,在GC收集器工作前,手动将holder设置为null值,就把holder所占用的局部变量表中的Slot清空了,因此,这次GC收集器工作时将holder之前引用的对象内存回收掉了。 当然,我们也可以用其他方法来将holder引用的对象内存回收掉,只要复用holder所占用的slot即可,比如在holder作用域之外执行一次读写操作。 为对象赋null值并不是控制变量回收的最好方法,以恰当的变量作用域来控制变量回收时间才是最优雅的解决办法。另外,赋null值的操作在经过虚拟机JIT编译器优化后会被消除掉,经过JIT编译后,System.gc()执行时就可以正确地回收掉内存,而无需赋null值。 性能调优 Java虚拟机的内存管理与垃圾收集是虚拟机结构体系中最重要的组成部分,对程序(尤其服务器端)的性能和稳定性有着非常重要的影响。性能调优需要具体情况具体分析,而且实际分析时可能需要考虑的方面很多,这里仅就一些简单常用的情况作简要介绍。 我们可以通过给Java虚拟机分配超大堆(前提是物理机的内存足够大)来提升服务器的响应速度,但分配超大堆的前提是有把握把应用程序的Full GC频率控制得足够低,因为一次Full GC的时间造成比较长时间的停顿。控制Full GC频率的关键是保证应用中绝大多数对象的生存周期不应太长,尤其不能产生批量的、生命周期长的大对象,这样才能保证老年代的稳定。 Direct Memory在堆内存外分配,而且二者均受限于物理机内存,且成负相关关系,因此分配超大堆时,如果用到了NIO机制分配使用了很多的Direct Memory,则有可能导致Direct Memory的OutOfMemoryError异常,这时可以通过-XX:MaxDirectMemorySize参数调整Direct Memory的大小。 除了Java堆和永久代以及直接内存外,还要注意下面这些区域也会占用较多的内存,这些内存的总和会受到操作系统进程最大内存的限制:1、线程堆栈:可通过-Xss调整大小,内存不足时抛出StackOverflowError(纵向无法分配,即无法分配新的栈帧)或OutOfMemoryError(横向无法分配,即无法建立新的线程)。 2、Socket缓冲区:每个Socket连接都有Receive和Send两个缓冲区,分别占用大约37KB和25KB的内存。如果无法分配,可能会抛出IOException:Too many open files异常。关于Socket缓冲区的详细介绍参见我的Java网络编程系列中深入剖析Socket的几篇文章。 3、JNI代码:如果代码中使用了JNI调用本地库,那本地库使用的内存也不在堆中。 4、虚拟机和GC:虚拟机和GC的代码执行也要消耗一定的内存。 原文出处:http://blog.csdn.net/ns_code/article/details/18076173
技术
分享
轩灵
2018-08-14
0
1,085
184
2018-07-07
typecho启用地址重写功能实现伪静态(Apache)
系统:Windows server 2008 r2 环境:Apache2.4+mysql5.5+php5.6 在Apache2.4我们首先要加载Rewrite模块,允许任何目录执行.htaccess。 在Apache/conf/httpd.conf配置文件 建议使用Notepad++修改造成编码错误。 在httpd.conf上找到 LoadModule rewrite_module modules/mod_rewrite.so 去掉前面注释#去掉。 将AllowOverride none 改成AllowOverride All Windows键+R换成cmd,cd到网站根目录。然后建立一个1.txt文边在文边里面写入 RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] 然后在执行 copy 1.txt .htaccess 该.htaccess文件必须放在网站根目录下 然后重启Apache服务。伪静态已经生效了。
默认分类
技术
轩灵
2018-07-07
0
1,111
140
2018-07-06
浏览器播放视频绿屏解决方案
浏览器播放视频绿屏 一、此设置是针对浏览器的硬件加速导致的视频播放绿屏 图片1.png图片IE浏览器 打开ie浏览器右上角的设置(齿轮图标) 图片2.png图片 打开Internet选项 图片3.png图片 点击高级 图片4.png图片 在高级的选项中找到“加速的图形”,并将下方“使用软件呈现而不使用 gpu 呈现*” 图片5.png图片 勾选或取消“使用软件呈现而不使用GPU呈现”(默认不选状态是硬件加速的,选取后取消硬件加速)。设置完重启浏览器 图片6.png图片360安全浏览器 打开360安全浏览器,点开浏览器右上角的选项,然后选择打开“选项/设置” 图片7.png图片 在打开的“选项/设置”中选择实验室 图片8.png图片 在实验室中将“智能开启硬件加速 ”这个勾取消就是关掉硬件加速了 图片9.png图片 重启浏览器就可以了 二、其他播放视屏情况客户端的基本是关掉硬件加速就好了。其他浏览器或者客户端可以在百度上找到关闭教程。 三、部分浏览器或者客户端可以直接设置。下面两个可能是右键绿屏出现的选项: 右键点击绿屏的视频,在选择取消硬件加速。 点击设置,在Adobe Flash Player设置中,将本地存储调整为无限。
默认分类
技术
分享
知识积累
# windows
轩灵
2018-07-06
0
2,453
121
2018-01-26
Brook - 一个跨平台(Linux/MacOS/Windows/Android/iOS)代理软件
What is Brook Brook is a cross-platform(Linux/MacOS/Windows/Android/iOS) proxy/vpn software. Brook's goal is to reduce the configuration steps. Keep it simple, stupid. Brook 是一款相当便捷的代理软件,多平台支持。 非常适合个人使用,与SS代理的区别则是新型加密更加避开GFW的追踪。 在最近的一个统计中,虽然brook的使用者比其他热门代理少,但是被Qiang的几率也小的多。 推荐个人或少部分团体使用,下面开始接受如何搭建以及推荐的一键搭建脚本。 搭建前准备:一台VPS服务器 以及一个聪明的大脑 如果搭建中提示 wget: command not found 的错误 这是你的系统精简的太干净了,wget都没有安装,所以需要安装wget。 CentOS系统: yum install –y wget Debian/Ubuntu系统: apt–get install –y wget 步骤一:下载brook 首先建立并进入文件夹(假设你当前目录是 /root ,那么 Brook的目录就是 /root/brook ): mkdir brook && cd brook 接下来获取brook的最新版本 brook_new_ver=`wget -qO- https://github.com/txthinking/brook/tags| grep "/txthinking/brook/releases/tag/"| head -n 1| awk -F 执行完后会输出获取的最新版本号,比如 v20180112 这样的日期格式,如果返回是空或者其他错误的内容,那么就代表获取失败。 如果输出失败,那就自己到 Github获取最新版本,才能继续以下步骤。手动获取到版本号 如v20180112,执行 brook_new_ver=v20180112(需要自己替换版本号)。 使用 uname -m 命令来判断VPS的位数,如果返回 x86_64 那就是64位,如果返回 i386或i686 那就是32位。 64位系统使用这个: wget –N —no–check–certificate “https://github.com/txthinking/brook/releases/download/${brook_new_ver}/brook” 32位系统使用这个: wget –N —no–check–certificate “https://github.com/txthinking/brook/releases/download/${brook_new_ver}/brook_linux_386” && mv brook_linux_386 brook 执行完上面的命令后,就已经把brook的文件下载到/root/brook文件夹中了,然后执行chmod +x brook 给予权限,然后执行mv brook /usr/bin即可。 步骤二:配置brook Run as a brook server (作为brook新版协议运行) 执行 brook server -l :9999 -p password (其中9999替换为你的端口 password替换为你的密码) Run as a brook stream server(作为brook旧版协议brook stream运行) 执行 brook streamserver -l :9999 -p password(其中9999替换为你的端口 password替换为你的密码) Run as multiple brook servers(作为多端口运行brook服务器) 执行以下代码 brook servers \ -l ":9999 password" \ -l ":8888 password" 其中8888,9999为端口号 password为密码 如果你也想作为Shadow-socks服务运行,可执行以下代码 Run as a shadow-socks server(单一端口运行) 执行brook ssserver -l :9999 -p password Run as multiple shadow-socks servers(多端口运行) brook ssservers \ -l ":9999 password" \ -l ":8888 password" 默认加密方式为aes-256-cfb 步骤三:配置防火墙 iptables -I INPUT -m state --state NEW -m tcp -p tcp --dport 8888 -j ACCEPT iptables -I INPUT -m state --state NEW -m udp -p udp --dport 8888 -j ACCEPT 其中8888为端口号,多端口时需重复替换执行代码。 其他问题 想要加入开机自启,执行代码 cp /usr/bin/brook /etc/init.d/brook chmod +x /etc/init.d/brook chkconfig --add brook chkconfig brook on 相关客户端请从官方下载 https://github.com/txthinking/brook/releases 下面推荐个一键脚本吧,最开始我是准备自己写个。没想到在逗比那里看见了,就直接用他这个吧,很不错的哦,适合小白和懒人。原文地址:https://doub.bid/brook-jc3/ 执行下面的代码下载并运行脚本。 wget -N --no-check-certificate https://softs.fun/Bash/brook.sh && chmod +x brook.sh && bash brook.sh # 如果上面这个脚本无法下载,尝试使用备用下载: wget -N --no-check-certificate https://raw.githubusercontent.com/ToyoDAdoubi/doubi/master/brook.sh && chmod +x brook.sh && bash brook.sh 运行脚本后会出现脚本操作菜单,选择并输入 1 就会开始安装。 其他操作 启动:/etc/init.d/brook start 停止:/etc/init.d/brook stop 重启:/etc/init.d/brook restart 查看状态:/etc/init.d/brook status 安装目录:/usr/local/brook 配置文件:/usr/local/brook/brook.conf 日志文件:/usr/local/brook/brook.log(注意正常情况下,日志是不会记录使用信息的,只会记录报错)
默认分类
技术
分享
轩灵
2018-01-26
0
4,817
101
上一页
1
...
13
14
15
16
下一页