范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

java后端面试题必问的JVM性能调优

  目录 前言 JVM性能调优 内存溢出错误 堆溢出错误和预判堆溢出的错误 虚拟机栈和本地方法栈溢出错误 方法区(元数据区)和运行时常量池溢出 直接内存区域的溢出 实践案例 如何正确利用大内存-高性能硬件上的程序部署策略 如何排查内存溢出错误 如何排查系统CPU性能指标异常-外部命令导致系统缓慢 前言
  JVM性能调优是一个很大的话题,很多中小企业的业务规模受限,没有迫切的性能调优需求,但是如果不知道JVM相关的理论知识,写出来的代码或者配置的JVM参数不合理时,就会出现很严重的性能问题,到时候开发就会像热锅上的蚂蚁,等待各方的炙烤。笔者一直在学习JVM相关的理论书籍,看过周志明老师的 深入理解Java虚拟机,也学习过 葛鸣老师的 实战Java虚拟机 ,但是在实际工作中,只有过寥寥几次的调优经验,几乎无处施展学习到的理论知识,致使知识大部分都存在在笔记和书本中,这次总结面试题,一是希望能够应对性能调优岗位相关的面试;二是希望总结一下具体的实战步骤,并努力吸收书中的实践案例,让自己的经验更丰富一些。 JVM性能调优内存溢出错误
  学习目的: 通过异常信息及时定位到发生内存溢出的运行时数据区域 了解什么样的代码会导致内存溢出,防止写出这样的代码 出现异常后该如何处理,也就是学习事中的处理手段
  内存溢出和内存泄露的区别 内存泄露:不该留存在进程中的内存数据,虽然很小,但是在经过多次长期的积累后,会导致内存溢出 内存溢出:程序申请内存时,内存不足的现象 堆溢出错误和预判堆溢出的错误
  如何复现出堆溢出错误? JVM参数部分:最大堆和最小堆设置相同并且设置的比较小,比如只有10M,这样就不会自动扩展堆 代码部分:在一个方法中不断地往集合中加入元素
  代码实践 package org.example;  import java.util.ArrayList; import java.util.List;  /**  * -Xmx10M -Xms10M -XX:+HeapDumpOnOutOfMemoryError  */ public class App {     static class OOMObject {         int a = 1;         long b = 2;         float c = 2.1f;     }      public static void main(String[] args) {         List list = new ArrayList<>();         while (true) {             list.add(new OOMObject());         }     } }
  正确的出现了我们想要的结果: java.lang.OutOfMemoryError: Java heap space Dumping heap to java_pid24476.hprof ... Heap dump file created [13268403 bytes in 0.077 secs] Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 	at java.util.Arrays.copyOf(Arrays.java:3210) 	at java.util.Arrays.copyOf(Arrays.java:3181) 	at java.util.ArrayList.grow(ArrayList.java:265) 	at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:239) 	at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:231) 	at java.util.ArrayList.add(ArrayList.java:462) 	at org.example.App.main(App.java:22)  Process finished with exit code 1
  如果把参数调大,调整20M,那么会报另外的error java.lang.OutOfMemoryError: GC overhead limit exceeded Dumping heap to java_pid8796.hprof ... Heap dump file created [27391983 bytes in 0.141 secs] Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded 	at org.example.App.main(App.java:19)  Process finished with exit code 1
  这个错误的原因是,JVMGC时间占据了整个运行时间的98%,但是回收只得到了2%可用的内存,至少出现5次,就会报这个异常。
  这个异常是Jdk1.6定义的策略, 通过统计GC时间来 预测是否要OOM了,提前抛出异常 ,防止OOM发生。
  案例心得: 堆内存溢出的识别:java.lang.OutOfMemoryError: Java heap space 或者 java.lang.OutOfMemoryError: GC overhead limit exceeded 死循环中不断创建对象这种代码应该规避 提前设置好自动转储的参数,出现异常能够恢复现场查看问题 事后排查思路:先用JvisualVM这样的软件查看具体对象,核查是内存溢出还是内存泄漏,如果确定没有泄露,需要排查堆的参数设置是否合理,从代码上分析对象存活时长比较长是否必要,是否可以优化等等。 虚拟机栈和本地方法栈溢出错误
  一般我们会遇到两种栈相关的错误: 单个线程中,不断的调用方法入栈,当栈深度超过虚拟机所允许的最大深度时,抛出StackOverflowError 不断地创建线程,创建线程就需要创建栈,当无法申请到足够的内存,就会报 unable to create new native thread错误
  如何复现? JVM参数:-Xss128k,每个线程的栈内存大小 代码部分:没有出口的递归调用
  代码实践 /**  * -Xss128k  */ public class App {     static int length = 0;      private static void reverse() {         length++;         reverse();     }      public static void main(String[] args) {         try {             reverse();         } catch (Throwable e) {             System.out.println("length:" + length);             throw e;         }     } }
  结果验证: length:1096 Exception in thread "main" java.lang.StackOverflowError 	at org.example.App.reverse(App.java:10) 	at org.example.App.reverse(App.java:11) 	at org.example.App.reverse(App.java:11) 	at org.example.App.reverse(App.java:11)     太多了,这里只截取部分
  关于unable to create new native thread这个异常,这里就不尝试了,因为可能会导致操作系统假死等问题。
  案例心得: 栈错误的识别:StackOverflowError 或者 java.lang.OutOfMemoryError: unable to create new native thread 没有出口的递归调用要避免;默认的JVM栈大小的参数针对一般的方法调用深度是足够的 如果必须要创建大量的常驻线程,并且是32位的虚拟机,要测试协调好  栈内存和其他内存的大小 ,防止出现溢出错误 事后排查思路:先确定是哪种错误,然后检查递归调用或者检查线程数 方法区(元数据区)和运行时常量池溢出方法区和运行时常量池异常
  在JDK1.6以及以前的版本中,运行时常量池是放在方法区中的,我们可以通过限制方法区的大小然后增大常量池来模拟溢出。
  如何模拟: JDK使用1.6版本,这里注意,要统一idea所有的版本,否则出错具体细节可以参考这里:idea 启动时报 error:java 无效的源发行版11 JVM参数:--XX:PermSize=10M -XX:MaxPermSize=10M 应用代码:使用String.intern方法不断创建新的常量对象到常量池中,并一直用集合保持强引用
  代码实践: package org.example;  import java.util.ArrayList; import java.util.List;   public class App {      public static void main(String[] args) {         int i = 0;         List list = new ArrayList();         while (true) {             list.add(String.valueOf(i++).intern());         }     } }
  结果: Exception in thread "main" java.lang.OutOfMemoryError: PermGen space 	at java.lang.String.intern(Native Method) 	at org.example.App.main(App.java from InputFileObject:15)  Process finished with exit code 1
  在JDK1.7以后,常量池就被移动到了堆中,所以如果限制了堆的大小,那么最终会报堆溢出异常或者预判堆异常的错误的。
  同样的代码使用JDK1.8版本测试,并指定了堆的最大和初始大小后,果然出现了我预计的异常。 参数:-XX:PermSize=10M -XX:MaxPermSize=10M -Xmx10M -Xms10M Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded 	at java.lang.Integer.toString(Integer.java:403) 	at java.lang.String.valueOf(String.java:3099) 	at org.example.App.main(App.java:13)
  如果加上不使用 预判断限制参数 -XX:-UseGCOverheadLimit,就会直接报堆溢出异常 -XX:PermSize=10M -XX:MaxPermSize=10M -Xmx10M -Xms10M -XX:-UseGCOverheadLimit Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 	at java.lang.Integer.toString(Integer.java:401) 	at java.lang.String.valueOf(String.java:3099) 	at org.example.App.main(App.java:13)
  说明,常量池分配在堆中。 元数据区异常
  JDK1.8之后,元数据区被放在了直接内存中,可以指定下面的参数来模拟溢出情况 JVM参数:-XX:MetaspaceSize=10M-XX:MaxMetaspaceSize=10M-XX:+HeapDumpOnOutOfMemoryError 代码:通过使用cglib生成大量的动态类
  代码实战:
  pom文件中添加cglib的引用          cglib         cglib         3.2.4  package org.example;  import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy;  import java.lang.reflect.Method;   public class App {      public static void main(String[] args) {         while (true) {             Enhancer enhancer = new Enhancer();             enhancer.setSuperclass(OOMObject.class);             enhancer.setUseCache(false);             enhancer.setCallback(new MethodInterceptor() {                 @Override                 public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {                     return methodProxy.invokeSuper(o, args);                 }             });             enhancer.create();         }     }      static class OOMObject {      } }
  运行结果: java.lang.OutOfMemoryError: Metaspace Dumping heap to java_pid26272.hprof ... Heap dump file created [3395669 bytes in 0.015 secs] Exception in thread "main" net.sf.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null 	at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:345) 	at net.sf.cglib.proxy.Enhancer.generate(Enhancer.java:492) 	at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:114) 	at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:291) 	at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:480) 	at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:305) 	at org.example.App.main(App.java:23) Caused by: java.lang.reflect.InvocationTargetException 	at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source) 	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 	at java.lang.reflect.Method.invoke(Method.java:498) 	at net.sf.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:413) 	at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:336) 	... 6 more Caused by: java.lang.OutOfMemoryError: Metaspace 	at java.lang.ClassLoader.defineClass1(Native Method) 	at java.lang.ClassLoader.defineClass(ClassLoader.java:756) 	... 11 more 案例心得元数据区和方法区错误的识别:java.lang.OutOfMemoryError: Metaspace;java.lang.OutOfMemoryError: PermGen space 元数据区的溢出一般和框架代码或者本地代码中大量创建动态类有关 核查问题时,也是根据具体的问题分析是哪个动态类被大量创建,是否有必要,是否需要调整方法区的大小。 直接内存区域的溢出
  直接内存区域,如果内存达到设置的MaxDirectMemorySize后,就会触发垃圾回收,如果垃圾回收不能有效回收内存,也会引起OOM溢出。
  如何复现? JVM参数:-XX:MaxDirectMemorySize,如果不指定,和-Xmx指定的最大堆一样 代码部分:使用unsafe不断的分配直接内存
  代码实战 package org.example;  import sun.misc.Unsafe;  import java.lang.reflect.Field;   public class App {      public static void main(String[] args) throws IllegalAccessException {         Field unsafeFiled = Unsafe.class.getDeclaredFields()[0];         unsafeFiled.setAccessible(true);         Unsafe unsafe = (Unsafe) unsafeFiled.get(null);         while (true) {             unsafe.allocateMemory(1024 * 1024);         }     }  }
  运行结果 Exception in thread "main" java.lang.OutOfMemoryError 	at sun.misc.Unsafe.allocateMemory(Native Method) 	at org.example.App.main(App.java:15)
  案例心得: 直接内存溢出的识别:Exception in thread "main" java.lang.OutOfMemoryError,并且dump出的堆栈文件不大 核查问题时,根据异常堆栈检查引发error的代码,一般都是NIO代码引起的。 实践案例如何正确利用大内存-高性能硬件上的程序部署策略
  高性能硬件程序部署主要有两种方式: 通过64位JDK使用来大内存 使用若干个32位的虚拟机建立逻辑集群以利用硬件资源
  如果程序是 对响应时间敏感 的系统,想配置大堆的前提是,要 保证应用的Full GC频率足够低 ,不会影响用户的使用,比如,可以设置深夜定时任务触发full-gc甚至自动重启应用服务器来保证可用空间在一个稳定的水平。控制Full GC频率的关键就是保证大多数对象都是朝生夕灭,不会短时间有大量对象进入老年代,引起频繁的FullGC。
  不仅如此,还需要考虑大堆带来的其他问题: 内存回收时间变长 如果出现OOM,因为堆过大,几乎无法分析dump文件 64位的JDK性能测试结果要弱于32位的JDK,并且占用内存也较大
  所以建议,如非必要, 尽可能使用第二种方式来部署以充分利用高性能硬件资源 。
  第二种方式就是集群部署方式,采用集群部署就需要考虑额外的问题,比如,如何保留用户的状态,一般有两种解决方案: 亲和式集群:同一个用户都转发到同一个服务器去处理 优点:实现简单,只需要在apache等负载均衡器中配置即可;网络流量较少,客户端只需要传递sessionID即可 缺点:用户和对应服务器绑定,一旦服务器宕机,用户的session状态即消失 apache中这样配置: worker.controller.sticky_session=true|false true为亲和式集群 worker.controller.sticky_session_force=true|false false为当服务器不可用,转发到其他服务器 共享session:集群内服务器共享session 优点:服务器宕机,用户也不会丢失session状态 缺点:在系统中引入了新的组件,提高了系统的复杂度,实现复杂度
  针对第二种方式,和第一种方式对比,也有自己的缺点,我们在设计系统机构时也需要考虑到: 同一台物理机器的上的资源竞争(并发写),首先会想到可以使用同步机制,可以学习锁设计中的分段锁和间隙锁,通过锁一部分来提高并发度;或者通过乐观锁的设计,不断循环更新直到成功;还可以考虑建立热访问资源,提前把一部分资源缓存到集中缓存中,通过集中式缓存减少磁盘IO竞争。 冗余的本地内存,可以考虑使用集中式内存数据库解决 资源池浪费,可以考虑使用JNDI(统一命名服务,我觉得和Springcloud中的统一配置中心核心思想是一致的,都是把配置文件统一放在一个地方,便于引用维护),但是也会带来新的复杂度
  总结: 高性能硬件的部署策略有两种,考虑到GC时间过长,堆转出日志无法分析等缺点,尽量选择多实例部署的逻辑集群方式 逻辑集群的部署方式要考虑 状态保持、资源竞争和资源冗余等情况,根据具体业务场景灵活应用。 如何排查内存溢出错误
  堆外内存溢出一般主要来源于操作系统对进程的内存限制 和 堆外内存回收的机制。
  针对操作系统堆进程的内存限制 。比如:32位的windows操作系统对进程的限制为2G,如果堆等其他区域划分的内存过大,那么留给直接内存区域的内存就非常小了。
  针对堆外内存的回收机制 。堆外内存需要等到满了之后,再在代码中触发System.gc来回收,如果服务器开启-XX:+DisableExplicitGC参数开关,那么就不会响应这次垃圾回收的请求。
  总结:
  因为限制以及其他区域不合理的参数配置,直接内存区域只有很小的一块内存;并且垃圾回收需要依靠手动触发System.gc来回收无法保证回收的可靠性,所以溢出就是必然的了。
  我这里又查阅了之前看过印象深刻的一个关于美团使用网络框架的一个堆外内存泄漏bug。这里给大家简单介绍下,原文详见这里:Netty堆外内存泄露排查盛宴
  首先作者通过nginx不断报5XX异常发现服务不可用,然后核查jvm发现频繁的fullgc导致用户线程阻塞(其实就是netty的nio线程),最后查出是log4j2在某个时点大量频繁的打印堆外内存不足的error日志导致的,所以这个问题的核心在于 排查堆外内存为何泄漏 。
  排查的步骤首先是基于异常的堆栈日志,找到对应的代码, 用反射机制每隔N秒观察堆外内存的大小 ,发现了堆外内存增长的规律。然后猜测原因, 模拟测试 查看是否可以复现问题,成功复现问题后,就能大约找到出现问题的代码,继续通过debug查找根源代码处,最终通过修改代码,重新build后最终解决问题。
  我个人认为这个问题解决的关键在于 开发者能够读懂框架自己使用变量统计堆外内存,然后得以跟踪这个变量最终解决问题 。我们在排查问题的时候如果也可以多想一些,多去琢磨框架报出异常的原因,也许就能找到解决问题的办法。 如何排查系统CPU性能指标异常-外部命令导致系统缓慢
  案例介绍:在做压力测试时发现系统的CPU指标异常,大量的时间被系统调用fork占用,最后核查代码发现这个fork系统调用是在每一个请求来临时,都会调用以获取系统相关的信息的,具体是使用Runtime.getRuntime().exec()来执行一段shell脚本,最后修改为通过java api调用,问题解决。
  案例收获: cpu等系统指标异常,一般都是来源于应用代码的某些操作,需要仔细检查代码中会导致系统调用的部分,采用其他替代方式实现。 java中获取操作系统信息,其实是一个很常见的操作,可以通过java api实现。
  最后给大家分享Spring系列的学习笔记和面试题,包含spring面试题、spring cloud面试题、spring boot面试题、spring教程笔记、spring boot教程笔记、最新阿里巴巴开发手册(63页PDF总结)、2022年Java面试手册。一共整理了1184页PDF文档。私信博主(777)领取,祝大家更上一层楼!!!
  原文作者:Ging
  原文出处:https://www.cnblogs.com/ging/p/13853741.html

为何风格女士都爱穿牛仔?TodaysTopic如果要列举出一款万能搭配单品的话,牛仔衬衫一定算一个。不浮夸,但你总能在时装周街拍里看见它的身影。牛仔衬衫的款式并不多,但用处却很大。你可以单穿内搭,甚至拿来满江红带火河南安阳汤阴岳飞庙图为进出岳飞庙的游客。李超庆摄图为参与背诵满江红免费游岳飞庙的游客。李超庆摄图为游客在观赏岳飞纪念馆馆藏珍品岳飞武官画像。李超庆摄图为游客在岳飞纪念馆里参观。李超庆摄图为游客在岳飞还没为城里人熟知的深山美食春耕进行时又是一年春天,万物复苏。经过三年疫雨洗礼。今年的春天格外不一样,春风轻拂,山间已是绿意盈盈。每年我最期盼下雨的应该就是三四月,不是我有多么喜欢下雨。因为每年的这个时候是采立讯精密国内大范围收购大陆台企,或与富士康平起平坐,不简单立讯精密工业股份有限公司(以下简称立讯精密)是一家技术导向公司,成立于2004年5月24日,专注于连接器连接线马达无线充电FPC天线声学和电子模块等产品的研发生产和销售高频产品开发云南再限电,有电解铝企业减产40,下游黄磷提价2000元继2022年9月两轮限电后,水电大省云南再度传出限电的消息。红星资本局了解到,本轮限电已波及云南当地的电解铝黄磷锌等行业,部分大型企业被要求减产,压减用电负荷。3月6日,电解铝企业澄明食品工业园CFO杨童雨以澄明模式,打造中部最大的火锅烧烤预制菜食材基地大河财立方记者郝楠楠吴海舒实习生张远芳文朱哲李博摄影3月8日上午,中原预制菜产业发展论坛在周口市鹿邑县举行,多位行业专家数百位企业家齐聚鹿邑县开发区澄明食品工业园,论道预制菜高质量18位女作家笔下的生活哲理,读完豁然开朗你有自己喜欢的女性作家吗?在她的笔触下,细腻生动深刻而不失温柔的表达,总能道出一份同感的心境。夜读在此梳理18位中外女性作家的亮眼名句,愿你读完,收获四两拨千斤的心得,一语道破情绪活在世上,放不下的就是一个缘点上方听金璐第1次和你说晚安文金璐主播金璐缘分,其实就是人间的牵绊,活在世上,放不下的就是一个缘。我们相遇了,接下来就会相随,也就是说,今天跟这个人有缘分了,就会跟他在一起,叫相随穷是有原因的一个人穷了很久,一眼就能看出来作者闻秋声原创文章,抄袭必究01引言人生,如棋局,善于做长期规划,每一步都能有所筹谋的人,往往能让自己有更大的赢面。而浑浑噩噩,每天都得过且过地混日子的人,往往会让自己陷入贫穷的境张欣你说服不了任何人不要妄想说服别人。世界上所有的事都是不以人的意志为转移。师太当年说我们能做主的事就是头发是否剪短,咖啡是否加糖,其他都是命运主宰(大意),可是人生总有一个阶段会认为人定胜天。后来觉细微处的幸福我的书桌上,还放着那听茶叶的铁皮罐子,上面写有中国茶的字样。茶叶我其实早已喝完,但是这个铁皮盒子我一直没有舍得扔掉。或许只是因为罐子上那三个略有古意的康熙字体,有一种古雅的味道让我
澳门新千亿赌王,凭什么是他?持股帮ApP财经点将录小心驶得万年船。随着三大叠码仔先后摊上事,一个负债累累,两个进去唱铁窗泪,再次验证了吕志和这位新赌王低调做人的先见之明。毕竟老话说得好,财不露白,富不露相,贵地下开采出新石油,中国石油这家油田取得新突破在油气田,新能源正承担着越来越多的戏份。日前,中国石油西南油气田用气田水提取出了工业级碳酸锂。该方法利用气田水预处理及吸附膜沉淀法耦合提锂的工艺,是国内首次自主在实验室从龙王庙组气女排世锦赛E组荷兰队无缘八强中国女排暂居第四京报体育记者孔宁北京时间10月8日凌晨,2022年女排世锦赛十六强复赛E组继续在荷兰鹿特丹举行,意大利队3比0轻取阿根廷队,继续领跑本组,东道主荷兰队0比3负于巴西队,彻底无缘八强110!U17亚预赛惨案不断,中国日本越南全胜,韩国23爆冷U17亚洲杯预选赛已经结束最新一轮的较量,提前诞生首支出线的球队,来自中亚的乌兹别克斯坦晋级决赛圈。此外,这个比赛日继续诞生多场大比分的惨案,中国队110最猛,澳大利亚队100也不东道主连败出局,美国队晋级八强,中国女排冲击第一,决战意大利2022年10月8日,女排世锦赛继续进行,F组塞尔维亚队美国队土耳其队晋级八强,波兰队和多米尼加队争夺最后的席位,E组意大利队巴西队日本队排名前三,但是都多打一轮,中国女排今晚决战两新秀出彩,刘正清11分刘礼嘉10分,上海9998战胜山西队CBA季前赛,上海队对阵山西队,上海队是上赛季的四强,山西是上赛季八强,山西队休赛季放走了西蒙斯和闫鹏飞,引进威姆斯,上海队引进三大外援,加上引进两大新人刘正清和刘礼嘉,上海实力明青海省8月房价下跌14,交易额大降64!高原楼市终于高处不胜寒青海是一个存在感很弱的省份。当谈到青藏高原时,您是否只想到西藏?当谈到可可西里昆仑山时,你是否意识到它们位于青海?青海省面积在全国排行第四,仅次于西藏新疆内蒙古。它的辽阔,涵盖了无万里长城八达岭,八达岭长城和万里长城是一个吗?一万里长城的介绍二八达岭长城的介绍三八达岭长城在万里长城中的地位四八达岭长城的游玩攻略八达岭长城是万里长城的一部分,万里长城指的是所有长城,而地名叫八达岭所以那段长城叫八达岭长城。贵州赤水河谷,一种说走就走的冲动已经好久没有出去玩耍,刚刚坐家里喝茶,突然想起了贵州的赤水河谷。记得第一次去那边应该是六七年前了吧,自驾爱车粗粗地走了一圈,无功无过,也没什么特别的感受。后来,有一次准备从贵州北上原来秦皇岛曾经来过这么多剧组,不说还真没留意,你知道几个?秦皇岛是全国唯一一座以皇帝帝号命名的城市,一首浪淘沙北戴河让秦皇岛闻名遐迩,天下尽知成为全国著名旅游休闲和度假的城市。依山傍海,景色美不胜收,更有北戴河天下第一关老龙头等等景点让中喜迎二十大贵州绿色发展闯新路新华社贵阳10月6日电题持续做好绿水青山就是金山银山这篇大文章贵州绿色发展闯新路新华社记者李自良潘德鑫汽车在贵州省黔西市新仁收费站刚下高速,两侧青山迎面,山间一条8米多宽的崭新旅游